/*
 *      datastruct.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#ifndef _DATASTRUCT_IMPL
#define _DATASTRUCT_IMPL

#include "datastruct.h"

#ifdef _WIN32 
static void setSon(processingTree *father){
#else
void setSon(processingTree *father){
#endif
	father->sons->father=father;
	father->sons->sign_num=father->sign_num;
	father->sons->step_num=father->step_num;
	father->sons->OP=NULL;
	father->sons->sons=NULL;
	father->sons->prevbro=NULL;
	father->sons->nextbro=NULL;
	father->sons->sign_mode=father->sign_mode;
}

#ifdef _WIN32 
static void setBro(processingTree *prevbro){ 
#else
void setBro(processingTree *prevbro){
#endif
	prevbro->nextbro->father=prevbro->father;
	prevbro->nextbro->sign_num=prevbro->sign_num;
	prevbro->nextbro->step_num=prevbro->step_num;
	prevbro->nextbro->OP=NULL;
	prevbro->nextbro->sons=NULL;
	prevbro->nextbro->prevbro=prevbro;
	prevbro->nextbro->nextbro=NULL;
	prevbro->nextbro->sign_mode=prevbro->sign_mode;
}


#ifdef _WIN32 
static void freeTree(processingTree *root){	
#else
void freeTree(processingTree *root){	
#endif
	if(root->sons!=NULL)freeTree(root->sons);
	if(root->nextbro!=NULL)freeTree(root->nextbro);
	if(root->OP!=NULL){
		free(root->OP);
		root->OP=NULL;
		root->prevbro=NULL;
		root->nextbro=NULL;
		root->sons=NULL;
		free(root);
		root=NULL;
	}
}

#ifdef _WIN32 
static int pTree_newnode(processingTree *this, char *where, int index,int type){
#else
int pTree_newnode(processingTree *this, char *where, int index,int type){
#endif
	int i=index;
	executing_func *localef;

	DBG_TREE ? printf("DBG_TREE - _%s_\n",&where[index]) : 0 ;
	

	switch(where[index]){
		case '(':
			/* Guessing new son founded */
			/*DBG*/DBG_TREE_PLUS ? printf("(") : 0 ;
			parenthesis++;
			this->sons=(processingTree *)malloc(sizeof(processingTree));
			setSon(this);
			i++;
			this->OP=(char *)calloc(sizeof(char),4);
			i=pTree_newnode(this->sons,where,i,NEW_SON);
			if(i>=0){
				if(where[i]!=WHERE_T){
					this->nextbro=(processingTree *)malloc(sizeof(processingTree));
					setBro(this);
					i=pTree_newnode(this->nextbro,where,i,NEW_BRO);
				}
			}
			break;
		case ')':
			/* Guessing end of brothers */
			/*DBG*/DBG_TREE_PLUS ? printf(")") : 0 ;
			switch(type){
				case NEW_SON:
					return -501;
					break;
				case NEW_BRO:
					i++;
					if(parenthesis>0) parenthesis--;
					else {return -501;}
					while(where[i]==' ') i++;
					this->prevbro->nextbro=NULL;
					free(this);
					break;
				default:
					return -501;
					break;
			}
			break;
		case 'A':
			/* Guessing AND founded */
			/*DBG*/DBG_TREE_PLUS ? printf(" AND ") : 0 ;
			switch(type){
				case NEW_SON:
					if((where[i+1]=='N') && (where[i+2]=='D')) return -501;
					break;
				case NEW_BRO:
					/* Quando un fratello è una AND si deve tagliare fuori dalla lista dei fratelli, collegando gli
					 * adiacenti dopo aver assegnato al padre l'operatore. Dopodichè si esegue free(this)*/
					if((where[i+1]=='N') && (where[i+2]=='D')){
						if(strncmp(this->father->OP,"OR",2)==0)	return -501;
						strncpy(this->father->OP,"AND\0",4);	
						this->nextbro=NULL;	
						i+=3;
						while(where[i]==' ')i++;	
						i=pTree_newnode(this,where,i,NEW_BRO);
					}else return -501;
					break;
				default:
					return -501;
					break;
			}
			break;
		case 'O':
			/* Guessing OR founded */
			/*DBG*/DBG_TREE_PLUS ? printf(" OR ") : 0 ;
			switch(type){
				case NEW_SON:
					if(where[i+1]=='R') return -501;
					break;
				case NEW_BRO:
					/* Quando un fratello è una OR si deve tagliare fuori dalla lista dei fratelli, collegando gli
					 * adiacenti dopo aver assegnato al padre l'operatore. Dopodichè si esegue free(this)*/
					if(where[i+1]=='R'){
						if(strncmp(this->father->OP,"AND",3)==0) return -501;
						strncpy(this->father->OP,"OR\0",3);
						this->nextbro=NULL;
						i+=2;
						while(where[i]==' ')i++;
						i=pTree_newnode(this,where,i,NEW_BRO);
					}else return -500;
					break;
				default:
					return -501;
					break;
			}
			break;
		case WHERE_T:
			/* Assuming end of query founded */
			/* If ptree_newnode is working correctly, you should never enter in this case */
			if(parenthesis!=0) return -502;
			break;
		default:
			/* Guessing custom filter founded */
			/*DBG*/DBG_TREE_PLUS ? printf("CUSTOM") : 0 ;
			for(localef=ef;localef;localef=localef->next){
				if((where[index]==localef->op[0]) && (where[index+1]==localef->op[1])){
					return localef->parse(this,where,index,i);
				}
			}
			break;
	}
	return i;
}


#ifdef _WIN32 
static iIp *HeadIns(IndexIp *top,iIp *cur,char type){
#else
iIp *HeadIns(IndexIp *top,iIp *cur,char type){
#endif
	iIp *newcur;
	
	newcur = (iIp *)malloc(sizeof(iIp));
	newcur->down=cur;
	if(cur!=NULL){
		cur->prev=newcur;
	}
	newcur->prev=newcur;
	if(type=='s'){
		top->sourceItem=newcur;
	}else if(type=='t'){
		top->targetItem=newcur;
	}
	newcur->type=type;
	newcur->top=top;
	cur=newcur;
	return cur;
}

#ifdef _WIN32 
static iIp *BottomIns(IndexIp *top,iIp *cur,char type){
#else
iIp *BottomIns(IndexIp *top,iIp *cur,char type){
#endif
	cur->down=(iIp *)malloc(sizeof(iIp));
	cur->down->prev=cur;
	cur = cur->down;
	cur->down=NULL;
	cur->type=type;
	cur->top=top;
	return cur;
}

#ifdef _WIN32 
static iIp *BetweenIns(IndexIp *top,iIp *old,iIp *cur,char type){
#else
iIp *BetweenIns(IndexIp *top,iIp *old,iIp *cur,char type){
#endif
	iIp *newcur;
	
	newcur = (iIp *)malloc(sizeof(iIp));
	newcur->down=cur;
	newcur->type=type;
	newcur->top=top;
	cur->prev=newcur;
	old->down=newcur;
	newcur->prev=old;
	cur=newcur;
	return cur;
}

#ifdef _WIN32 
static dailyAlertList *newyList(yList *top,int year){
#else
dailyAlertList *newyList(yList *top,int year){
#endif
	yList *curyear;
	dailyAlertList *curday;
	
	
	curyear=top;
	curyear->yy=year;
	curyear->next=NULL;
	curyear->top=(dailyAlertList *)malloc(sizeof(dailyAlertList));
	curday=curyear->top;
	curday->next=NULL;
	curday->prev=curday;
	curday->top=curyear;
	return curday;
}

#ifdef _WIN32 
static dailyAlertList *tsHeadIns(yList *top,dailyAlertList *cur){
#else
dailyAlertList *tsHeadIns(yList *top,dailyAlertList *cur){
#endif
	dailyAlertList *newcur;
	
	top->top = (dailyAlertList *)malloc(sizeof(dailyAlertList));
	newcur=top->top;
	newcur->prev=newcur;
	newcur->next=cur;
	newcur->top=top;
	if(cur!=NULL){
		cur->prev=newcur;
	}
	cur=newcur;
	return cur;
}

#ifdef _WIN32 
static dailyAlertList *tsBottomIns(yList *top,dailyAlertList *cur){
#else
dailyAlertList *tsBottomIns(yList *top,dailyAlertList *cur){
#endif
	cur->next=(dailyAlertList *)malloc(sizeof(dailyAlertList));
	cur->next->prev=cur;
	cur = cur->next;
	cur->next=NULL;
	cur->top=top;
	return cur;
}

#ifdef _WIN32 
static dailyAlertList *tsBetweenIns(yList *top,dailyAlertList *old,dailyAlertList *cur){
#else
dailyAlertList *tsBetweenIns(yList *top,dailyAlertList *old,dailyAlertList *cur){
#endif
	dailyAlertList *newcur;
	
	newcur = (dailyAlertList *)malloc(sizeof(dailyAlertList));
	newcur->prev=old;
	newcur->next=cur;
	newcur->top=top;
	if(cur!=NULL){
		cur->prev=newcur;
	}
	old->next=newcur;
	cur=newcur;
	return cur;
}

#ifdef _WIN32 
static xmlNodeList *newxmlNodeList(void){
#else
xmlNodeList *newxmlNodeList(void){
#endif
	xmlNodeList *l;
	l=(xmlNodeList *)malloc(sizeof(xmlNodeList));
	l->item=NULL;
	l->next=NULL;	
	return l;
}

#ifdef _WIN32 
static posList *newposList(void){
#else
posList *newposList(void){
#endif
	posList *l;
	
	l=(posList *)malloc(sizeof(posList));
	l->list=NULL;
	l->next=NULL;	
	return l;
}

#ifdef _WIN32 
static AlertList *AlertList_headInsert(AlertList *l,xmlNode *item){
#else
AlertList *AlertList_headInsert(AlertList *l,xmlNode *item){
#endif
	AlertList *cur;
	int i;
	
	if(l==NULL){
		l=(AlertList *)malloc(sizeof(AlertList));
		l->next=NULL;
	}else{
		cur=(AlertList *)malloc(sizeof(AlertList));
		cur->next=l;
		l=cur;
	}
	l->root=item;
	l->ip_index=NULL;
	l->time_index=NULL;
	for(i=0;i<256;i++){
		l->match[i]&=0;
	}
	return l;
}

#ifdef _WIN32 
static stringList *stringList_headInsert(stringList *sel,char *selStr){
#else
stringList *stringList_headInsert(stringList *sel,char *selStr){
#endif
	stringList *cur;
	
	if(sel==NULL){
		sel=(stringList *)malloc(sizeof(stringList));
		sel->next=NULL;
	}else{
		cur=(stringList *)malloc(sizeof(stringList));
		cur->next=sel;
		sel=cur;
	}
	sel->str=(char *)calloc(sizeof(char),strlen(selStr)+1);
	strncpy(sel->str,selStr,strlen(selStr));
	return sel;
}

#ifdef _WIN32
static xmlNodeList *freexmlNodeList(xmlNodeList *list_to_delete){
#else
xmlNodeList *freexmlNodeList(xmlNodeList *list_to_delete){
#endif
	if(list_to_delete!=NULL){
		freexmlNodeList(list_to_delete->next);
		list_to_delete->item=NULL;
		list_to_delete->next=NULL;
		free(list_to_delete);
		list_to_delete=NULL;
	}
	return NULL;
}

#ifdef _WIN32
static void freestringList(stringList *list_to_delete){
#else
void freestringList(stringList *list_to_delete){
#endif
	if(list_to_delete!=NULL){
		freestringList(list_to_delete->next);
		free(list_to_delete->str);
		list_to_delete->str=NULL;
		free(list_to_delete);
		list_to_delete=NULL;
	}
	return;
}

#endif
